package com.xl.studentpass.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xl.studentpass.entity.*;
import com.xl.studentpass.entity.po.OrderOverViewPo;
import com.xl.studentpass.entity.po.PostingInfoPo;
import com.xl.studentpass.entity.po.UserDetailPo;
import com.xl.studentpass.entity.vo.UserVo;
import com.xl.studentpass.mapper.CommentMapper;
import com.xl.studentpass.mapper.CommunityMapper;
import com.xl.studentpass.mapper.ImageMapper;
import com.xl.studentpass.mapper.UserMapper;
import com.xl.studentpass.service.BaseAreaService;
import com.xl.studentpass.service.CommunityService;
import com.xl.studentpass.service.UserService;
import com.xl.studentpass.utils.AesUtils;
import com.xl.studentpass.utils.ImageIdType;
import com.xl.studentpass.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.management.RuntimeMBeanException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static com.xl.studentpass.service.impl.AcceptTaskServiceImpl.getStrings;
import static com.xl.studentpass.utils.ImageIdType.ORDER;
import static com.xl.studentpass.utils.ImageIdType.TASK;
import static com.xl.studentpass.utils.TaskOrderStatus.FAVORITE;
import static com.xl.studentpass.utils.TaskOrderStatus.LIKE;

/**
 * @author: xl
 * @createTime: 2023/5/28 14:15:00
 * @program: student-pass
 * @e-mail: 2199396150@qq.com
 * @description:
 */
@Service
@Slf4j
@CacheConfig(cacheNames = "user")
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {
    @Resource
    UserMapper userMapper;
    @Value("${password.bKey}")
    private String bKey;
    @Resource
    ImageMapper imageMapper;
    @Resource
    CommunityMapper communityMapper;
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Resource
    CommunityService communityService;
    @Resource
    CommentMapper commentMapper;
    @Resource
    BaseAreaService baseAreaService;


    @Override
    public R update(UserVo user) {

        int userId = StpUtil.getLoginIdAsInt();

        String password = user.getPassword();
        String encrPasswd = AesUtils.encrypt(password, bKey);

        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(user, userEntity);

        userEntity.setId(userId);

        userEntity.setGender("男".equals(user.getGenderName()) ? 0 : 1);

        userEntity.setEncrPassword(encrPasswd);

        boolean flag = this.updateById(userEntity);
        log.info("id=======>" + userEntity.getId());
        if (flag) {
            return R.ok("修改成功");
        }
        return R.error("修改失败");
    }

    @Override
    public List<TaskInfoEntity> getTaskByStatus(Integer userId, Integer statusId) {
        log.info("查询任务数据   statusId=====>" + statusId);
        List<TaskInfoEntity> taskByStatus = this.userMapper.getTaskByStatus(userId, statusId);
        taskByStatus.forEach(x -> x.setImageUrls(getStrings(x.getId(), imageMapper, TASK)));
        return taskByStatus;
    }

    @Override
    public R updatePictureById(Integer userId, List<String> urls) {
        try {
            UserEntity user = userMapper.selectById(userId);
            if (ObjectUtils.isEmpty(user)) {
                return R.error("头像上传失败");
            }
            userMapper.updateById(user);
            return R.ok("头像上传成功");
        } catch (RuntimeMBeanException e) {
            log.error(e.getMessage());
            return R.error("头像上传失败");
        }
    }

    @Override
    public List<OrderOverViewPo> getOrderByStatus(Integer userId, Integer statusId) {
        log.info("查询订单数据  statusId=====>" + statusId);
        List<OrderOverViewPo> overViewPos = this.userMapper.getOrderByStatus(userId, statusId);
        log.info("查询订单数据 ========>" + overViewPos.toString());
        overViewPos.forEach(x -> x.setImageUrls(getImageUrls(x.getOrderId(), ORDER)));
        return overViewPos;
    }

    private List<String> getImageUrls(Integer id, ImageIdType idType) {
        return getStrings(id, imageMapper, idType);
    }

    @Override
    //@Cacheable("userdetail")
    public UserDetailPo getUserDetail() {

        int loginUserId = StpUtil.getLoginIdAsInt();

        UserEntity user = this.getById(loginUserId);

        UserDetailPo userDetailPo = new UserDetailPo();

        BeanUtil.copyProperties(user, userDetailPo);

        if (!ObjectUtils.isEmpty(user.getGender())) {
            userDetailPo.setGenderName(user.getGender() == 0 ? "男" : "女");
        }


        List<String> imageUrls = getImageUrls(user.getId(), ImageIdType.USER);
        if (!ObjectUtils.isEmpty(imageUrls) && imageUrls.size() > 0) {
            userDetailPo.setImageUrl(imageUrls.get(0));
        }

        if (!ObjectUtils.isEmpty(user.getSchoolId())) {
            SchoolInfoEntity schoolInfoById = baseAreaService.getSchoolInfoById(user.getSchoolId());
            if (!ObjectUtils.isEmpty(schoolInfoById)) {
                userDetailPo.setSchoolName(schoolInfoById.getSchoolName());
            }
        }
        return userDetailPo;
    }

    @Override
    public R getPostingInfosByFavorite(Integer userId) {
        List<PostingInfoPo> postingInfoPos = getPostingInfoPoByUserId(userId, FAVORITE.getStatusName());
        return R.ok().put("postingInfoPos", postingInfoPos);
    }

    @Override
    public R getPostingInfosByLike(Integer userId) {
        List<PostingInfoPo> postingInfoPos = getPostingInfoPoByUserId(userId, LIKE.getStatusName());
        return R.ok().put("postingInfoPos", postingInfoPos);
    }

    /**
     * @param userId 用户
     * @param name   like or favorite
     * @return List<帖子信息>
     */
    private List<PostingInfoPo> getPostingInfoPoByUserId(Integer userId, String name) {
        String key = "userId:" + userId;
        Set<Object> keys = stringRedisTemplate.opsForHash().keys(key);
        ArrayList<CommunityEntity> communities = new ArrayList<>();
        for (Object o : keys) {
            String hashKey = (String) o;
            String[] fields = hashKey.split(":");
            if (ObjectUtils.isEmpty(fields) || fields.length <= 0) {
                return null;
            }
            if (fields[0].contains(name)) {
                Integer communityId = Integer.parseInt(fields[1]);
                CommunityEntity byId = communityService.getById(communityId);
                communities.add(byId);
            }
        }
        return communityService.getPostingInfoPo(communities);
    }

    @Override
    public R getPostingInfosByComment(Integer userId) {
        LambdaQueryWrapper<CommentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CommentEntity::getUserId, userId);
        List<CommentEntity> comments = commentMapper.selectList(wrapper);
        Set<Integer> communityIds = new HashSet<>();
        comments.forEach(x -> communityIds.add(x.getCommunityId()));
        List<CommunityEntity> communities = communityMapper.selectBatchIds(communityIds);
        List<PostingInfoPo> postingInfoPos = communityService.getPostingInfoPo(communities);
        return R.ok().put("postingInfoPos", postingInfoPos);
    }
}
